package com.seckill.timer;

import com.seckill.commons.Constants;
import com.seckill.goods.model.Goods;
import com.seckill.goods.service.GoodsService;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;

@Component
@EnableScheduling
public class SecKillTimer {
    @Resource
    private GoodsService goodsService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private AmqpTemplate amqpTemplate;
    /**
     * 配置定时任务，每秒钟执行一次，用于将商品信息初始化到Redis中
     * 注意：
     *   实际项目中，不能是每秒钟一次，应该是特定的时间，例如活动开始前或每天固定时间如23:55
     *   将未来一天的商品初始化到Redis中
     */
    @Scheduled(cron = "* * * * * *")
    public void initSecKillTimer(){
        //获取所有商品信息，
        //实际项目不能获取所有商品信息，应该根据系统时间获取将开始开始活动的所有商品信息
        List<Goods>list=goodsService.getGoodsAll();
        list.forEach(goods->{
            //使用统一Key前缀+商品随机名作为Key
            //使用商品库存作为value将商品信息初始化到Redis中
            //setIfAbsent 用于将数据写入Redis，如果Key存在则放弃写入，如果Key不存在则完成写入
            stringRedisTemplate.opsForValue().setIfAbsent(Constants.GOODS_STORE+goods.getRandomName(),goods.getStore()+"");
        });
    }

    /**
     * 配置定时任务每5秒钟执行一次，用于扫描Redis中订单备份数据，如果存在掉单行为则将数据补发到MQ中即可
     * 实际项目不能时每5秒钟一次，应该是更长的时间，例如10分钟或15分钟等等
     */
    @Scheduled(cron = "0/5 * * * * *")
    public void diaoDan(){
        //计算当前系统时间5分钟之前的毫秒值作为从Redis中获取数据的最大分数
        long maxScore=System.currentTimeMillis()-1000*60*5;
        //从Redis中的订单备份数据的ZSet集合中获取5分钟之前的订单
       Set<String>orderSet=stringRedisTemplate.opsForZSet().rangeByScore(Constants.ORDERS,0,maxScore);
       orderSet.forEach(orderStr-> amqpTemplate.convertAndSend("secKillExchange","",orderStr));
    }
}
